GM = GM or gmod.GetGamemode() //For manual reloading

GM.recipes = {}

if CLIENT then
	GM.recipes = {}
	GM.recipes["Campfire"] = { ["tools"] = {
												crystal = 1 },
							   ["products"] = {
							   					campfire = 1 },
							   ["reagents"] = {
							   					wood = 4,
							   					rock = 1 },
							  } //Start player off with campfire so he can get use to the game
end

function GM:ParseRecipes() //Server only
	//for k,recipefile in pairs(file.Find("ws/recipes/*.txt", "DATA")) do
	for k,recipefile in pairs(file.Find("wintersurvival/content/data/ws/recipes/*.txt", LUA_PATH)) do
		local recipefile = recipefile:sub(1,#recipefile-4)
		//local str = file.Read("ws/recipes/"..recipefile..".txt")
		local str = file.Read("gamemodes/wintersurvival/content/data/ws/recipes/"..recipefile..".txt", true)
		local lines = string.Explode("\n",str)
		
		local title = table.remove(lines,1)
		self.recipes[title] = {}
		for i = 1,#lines do
			
			local v = lines[i]
			local a = v:find("=")
			if a then
				local k = v:sub(1,a-1)
				local v = v:sub(a+1)
				if string.find(v,",") then
					self.recipes[title][k] = string.Explode(",",v)
				else
					self.recipes[title][k] = {v}
				end
			end
		end
	end
end

function GM.doRecipe(pl,cmd,args) //Server only
	if CLIENT then
		return
	end
	local self = gmod.GetGamemode()
	local uid = pl:UniqueID()
	local inv = self.pldat[uid].inventory
	
	//PrintTable(args)
	local has = function(tab,item)
		for k,v in pairs(tab) do
			if v == item then
				return true
			end
		end
		return false
	end
	
	local possible = {}
	
	for k,v in pairs(self.recipes) do
		//Msg(k,":\n\tStage 1\n")
		local good = true
		for i,o in pairs(v.reagents) do
			if not has(args,o) then
				good = false
			end
		end
		
		if good then
			//Msg("\tStage 2\n")
			for i,o in pairs(args) do
				if (not has(v.reagents,o)) and (not has(v.tools or {},o)) then //Tools are optional since they are not consumed
					//Msg("\t\tHad an extra ",o,"!\n")
					good = false
				end
			end
		end
		
		if good then
			//Msg("\tStage 3\n")
			//Do we have the proper tools?
			for i,o in pairs(v.tools or {}) do
				if not (inv[o] and inv[o].quantity > 0) then
					//Msg("\t\tMissing a ",o,"!\n")
					good = false
				end
			end
		end
		
		if good then
			//Msg("\tPass!\n")
			table.insert(possible,k)
		end
	end
	
	//PrintTable(possible)
	
	if #possible < 1 then
		return
	end
	
	umsg.Start("wsRecAcq",pl)
		umsg.Short(#possible)
		
		for k,v in pairs(possible) do
			umsg.String(v)
			for n,m in pairs{"products","tools","reagents"} do
				local m = self.recipes[v][m] or {}
				
				umsg.Short(#m)
				for i,o in pairs(m) do
					umsg.String(o)
				end
			end
		end
	umsg.End()
	
	if #possible > 1 then
		//error("More than one possible solution in recipe solver!\n")
		//Solved by adding to recipe list
		
		umsg.Start("wsGotoRec",pl)
		umsg.End()
		return
	end
	
	local recipe = self.recipes[possible[1]]
	
	self.doListedRecipe(pl,cmd,{possible[1]})
end

if SERVER then
	concommand.Add("wsrecipe",GM.doRecipe)
end

if CLIENT then
	usermessage.Hook("wsRecAcq",function(msg)
		local self = gmod.GetGamemode()
		local num = msg:ReadShort()
		if num > 0 then
			for k = 1,num do
				local v = msg:ReadString()
				self.recipes[v] = {}
				
				for n,m in pairs{"products","tools","reagents"} do
					self.recipes[v][m] = {}
					local m = self.recipes[v][m]
					
					local num = msg:ReadShort()
					if num > 0 then
						for i=1,num do
							local class = msg:ReadString()
							if not m[class] then
								m[class] = 1
							else
								m[class] = m[class] + 1
							end
						end
					end
				end
			end
		end
	end)
	usermessage.Hook("wsGotoRec",function(msg)
		local self = gmod.GetGamemode()
		local inv = self.inventory
		
		if type(inv.menuInventory) == "table" and inv.menuInventory.main:IsVisible() then
			inv.menuInventory.main:GetTable().tab = 2
		end
	end)
end

function GM.doListedRecipe(pl,cmd,args) //Server only
	local self = gmod.GetGamemode()
	local uid = pl:UniqueID()
	local inv = self.pldat[uid].inventory
	
	//PrintTable(args)
	local has = function(tab,item)
		for k,v in pairs(tab) do
			if v == item then
				return true
			end
		end
		return false
	end
	
	local recipe = args[1]
	
	if not (recipe and self.recipes[recipe]) then
		//Msg("\tInvalid recipe: ",recipe,"\n");
		return
	end
	recipe = self.recipes[recipe]
	//Make sure we have sufficient quantities
	
	//Msg("\tTesting...\n")
	
	//Tools
	local ingtab = {}
	for k,v in pairs(recipe.tools or {}) do
		if not ingtab[v] then
			ingtab[v] = 1
		else
			ingtab[v] = ingtab[v]+1
		end
	end
	//Reagents
	for k,v in pairs(recipe.reagents) do
		if not ingtab[v] then
			ingtab[v] = 1
		else
			ingtab[v] = ingtab[v]+1
		end
	end
	
	//Enough?
	for k,v in pairs(ingtab) do
		if not (inv[k] and inv[k].quantity >= v) then
			//Not enough k's!
			//Msg("\tNot enough ",k,"s!\n")
			umsg.Start("wsGotoRec",pl)
			umsg.End()
			return
		end
	end
	
	//Take away reagents (Re-do ingtab)
	local ingtab = {}
	for k,v in pairs(recipe.reagents) do
		if not ingtab[v] then
			ingtab[v] = 1
		else
			ingtab[v] = ingtab[v]+1
		end
	end
	
	//Products
	//We have enough to execute!
	for k,v in pairs(ingtab) do
		pl:WSGive(k,v*-1)
	end
	for k,v in pairs(recipe.products) do
		pl:WSGive(v,1)
	end
end

if SERVER then
	concommand.Add("wslistedrecipe",GM.doListedRecipe)
end
